function jObject(obj, type) {
    this.o = obj;
    this.t = type;
};
jObject.prototype.getType = function () {
    if (this.t == null) {
        return typeof (obj);
    }
    else {
        return this.t;
    }
}

jObject.prototype.support = function (array) {
    return array.indexOf(this.getType()) >= 0;
}

jObject.prototype.contains = function (obj) {
    if (!this.support([])) return null;
    return this.o.indexOf(obj)>0
}

function jString(str) {
    if (!str) return null;
    this.o = str.toString();    
}

jString.prototype = {
    len: function () { return this.o.length; },
    index: function (index) {
        //if out of scope return ''
        return this.o.charAt(index)
    },
    charAt: function (index) {
        //if out of scope return ''
        return this.o.charAt(index)
    },
    ascii: function (index) {
        //If there is no character at the specified index, NaN is returned.
        index = index || 0;
        return this.o.charCodeAt(index);
    },
    charCodeAt: function (index) {
        //If there is no character at the specified index, NaN is returned.
        return this.o.charCodeAt(index);
    },
    concat: function () {
        var args = [];
        for (var i = 0; i < arguments.length; i++) args.push(arguments[i]);
        return this.o.concat.apply(this.o, args);
    },
    indexOf: function (subString, startIndex) {
        return this.o.indexOf(subString, startIndex);
    },
    lastIndexOf: function (subString, startIndex) {
        return this.o.lastIndexOf(subString, startIndex);
    },
    localeCompare: function (stringExp) {
        return this.o.localeCompare(stringExp)
    },
    match: function (rgExp) {
        return this.o.match(rgExp)
    },
    replace: function (rgExp, replaceText) {
        return this.o.replace(rgExp, replaceText)
    },
    replaceAll: function (str, replaceText, ignoreCase) {
        ignoreCase = ignoreCase || false;
        if (ignoreCase) {
            return this.o.replace(new RegExp(str, "gmi"), replaceText);
        }
        else {
            return this.o.replace(new RegExp(str, "gm"), replaceText);
        }
    },
    search: function (rgExp) {
        return this.o.search(rgExp)
    },
    slice: function (start, end) {
        return this.o.slice(start, end)
    },
    split: function (separator, limit) {
        return this.o.split(separator, limit)
    },
    substr: function (start, length) {
        return this.o.substr(start, length)
    },
    substring: function (start, end) {
        return this.o.substring(start, end)
    },
    toLocaleLowerCase: function () {
        return this.o.toLocaleLowerCase()
    },
    toLocaleUpperCase: function () {
        return this.o.toLocaleUpperCase()
    },
    toUpperCase: function () {
        return this.o.toUpperCase()
    },
    toLowerCase: function () {
        return this.o.toLowerCase()
    },
    trim: function () {
        return this.o.trim()
    },
    toString: function () {
        return this.o.toString()
    },
    valueOf: function () {
        return this.o.valueOf()
    },

    left: function (length) {
        return this.o.substr(0, length);
    },
    right: function (length) {
        return this.o.substr(this.o.len() - length, length);
    },
    format: function () {
        var args = arguments;
        var res = this.o.replace(/\{(\d+)\}/g, function ($0, $1) { return args[parseInt($1)]; });
        return res;
    }


};

jString.format = function () {
    if (arguments.length == 0) return null;

    var str = arguments[0];
    var args = arguments;
    var res = str.replace(/\{(\d+)\}/g, function ($0, $1) {
        return args[parseInt($1) + 1]; 
    });
    return res;
} 